#include "Object.h"
#include <iostream>
#include <QMutexLocker>
#include <assert.h>
#include "OOPUtils.h"
#include "_ObjectCreateHelper.h"
#include "ResourceLoader.h"
#include "ResourceSaver.h"



_NS_OOP_BEGIN



// REMARKS: set _refNum to 1 is to prevent a Ptr destroying the object in the 
// situation that it is created in the constructor. _refNum will be corrected in 
// NewPtr's constructor. Belows the same.
Object::Object () :
_name (_ObjectCreateHelper::ref ().nameOfNewingObject ()),
_syncStatus (NEW),
_refNum (1) 
{
	if (!_ObjectCreateHelper::ref ().isNewingObject ())
		OOPTHROW (CreateObjectOnStackException ());
	_ObjectCreateHelper::ref ().recordNewingObjectFinished ();
}



Object::~Object ()
{
	assert (_refNum == 0);
}



void*
Object::operator new (size_t size)
{
	void* p = ::operator new (size, std::nothrow);
	if (p == NULL) {
		ResourceManager::ref ()._clean ();
		p = ::operator new (size);
	}
	_ObjectCreateHelper::ref ().recordNewingObject ("");
	return p;
}



void*
Object::operator new (size_t size, const QString& r_name)
{
	void* p = ::operator new (size, std::nothrow);
	if (p == NULL) {
		ResourceManager::ref ()._clean ();
		p = ::operator new (size);
	}
	_ObjectCreateHelper::ref ().recordNewingObject (r_name);
	return p;
}



void
Object::operator delete (void* ptr, const QString& r_name)
{
	::operator delete (ptr);
}



void
Object::operator delete (void* ptr)
{
	::operator delete (ptr);
}



const QString&
Object::name () const
{
	return _name;
}
void
Object::name (const QString& r_val)
{
	if (r_val.isEmpty ())
		OOPTHROW (InvalidArgumentException (
				QString ("name to set cannot be empty")));
	_name = r_val;
}



int
Object::getRefNum () const
{
	return _refNum;
}



bool
Object::isObject (void* ptr)
{
	return false;
}



bool
Object::isObject (Object* ptr)
{
	return true;
}



void
Object::__contentModified ()
{
	if (_syncStatus == NOT_CHANGED)
		_syncStatus = MODIFIED;
}



void
Object::_incrRef ()
{
	QMutexLocker locker (&_mutex);
	++_refNum;
#ifdef OOPUTILS_DEBUG
	std::cout << "0x" << this << ": + ref to " << _refNum << std::endl;
#endif
}



void
Object::_decrRef ()
{
	QMutexLocker locker (&_mutex);
	--_refNum;
#ifdef OOPUTILS_DEBUG
	std::cout << "0x" << this << ": - ref to " << _refNum << std::endl;
#endif
}



_NS_OOP_END